module LC_3 #(parameter DATA_SIZE = 16)
             (CLK,
              RESET);
    input CLK,RESET;
    wire [15:0] BUS;
    /**********************************/
    //      PC-Counter & MARMUX        //
    /**********************************/
    wire LD_MAR,LD_MDR,LD_IR,LD_PC;
    wire tri_PC_SEL,tri_RAM_SEL,ADDR1MUX_SEL,MARMUX_SEL;
    wire [1:0]  PCSEL,ADDR2MUX_SEL;
    wire [15:0] OFFSET,DIRECT,PC_OUT,MARMUX_OUT,MAR_OUT,MDR_OUT,IR_OUT,PC_add_OUT,ADDR1MUX_OUT,ADDR2MUX_OUT;
    wire [15:0] SR1_OUT,SEXT8;
    
    pc PC(.CLK(CLK),.RESET(RESET),.PCSEL(PCSEL),.OFFSET(PC_add_OUT),.DIRECT(DIRECT),.LD(LD_PC),.PC_OUT(PC_OUT));
    tristate #(16) tri_PC(.D_OUT(BUS),.D_IN(MARMUX_OUT),.SEL(tri_PC_SEL));
    mux_2to1#(16) ADDR1MUX(.D_IN0(SR1_OUT),.D_IN1(PC_OUT),.D_OUT(ADDR1MUX_OUT),.SEL(ADDR1MUX_SEL));
    mux16_4to1#(16) ADDR2MUX(.SEL(ADDR2MUX_SEL),.D_IN0({16{1'b0}}),.D_IN1(SEXT8),.D_IN2(),.D_IN3(),.D_OUT(ADDR2MUX_OUT));
    add_16 PC_add (.CYI(1'b0),.OP_A(ADDR1MUX_OUT),.OP_B(ADDR2MUX_OUT),.CYO(),.SUM(PC_add_OUT));
    mux_2to1 #(16) MARMUX(.D_IN0(),.D_IN1(PC_add_OUT),.SEL(MARMUX_SEL),.D_OUT(MARMUX_OUT));
    
    
    /**********************************/
    //      MAR  &  RAM &  MDR        //
    /**********************************/
    wire MDR_SEL,RAM_WE;
    wire[15:0]MDR_IN,ram_out;
    //register_16#(16) MAR(.DATA_IN(BUS),.DATA_OUT(MAR_OUT),.LD(LD_MAR));
    DFF MAR(.CLK(CLK),.D(BUS),.Q(MAR_OUT),.LD(LD_MAR));
    ram #(16,16) Insrt_DATA_Memory(.DATA_IN(MDR_OUT),.WE(RAM_WE),.ADDRESS(MAR_OUT),.DATA_OUT(ram_out));
    mux_2to1 #(16) MDRMUX(.D_IN0(ram_out),.D_IN1(BUS),.D_OUT(MDR_IN),.SEL(MDR_SEL));
    DFF MDR(.CLK(CLK),.D(MDR_IN),.Q(MDR_OUT),.LD(LD_MDR));
    //register_16_old#(16) MDR(.DATA_IN(MDR_IN),.DATA_OUT(MDR_OUT),.LD(LD_MDR));
    tristate #(16) tri_RAM(.D_OUT(BUS),.D_IN(MDR_OUT),.SEL(tri_RAM_SEL));
    
    
    /**********************************/
    //  IR  &   Registerfile &   ALU   //
    /**********************************/
    wire LD_Registerfile,SR2MUX_SEL,tri_ALU_SEL;
    wire [1:0] ALU_SEL;//ALU的操作控制信号
    wire [3:0] OPcode;
    wire [2:0] Dst_addr,Src1_addr,Src2_addr;
    //wire [15:0]SR1,SR2,SR1_OUT,SR2_OUT,ALU_OUT;
    wire [15:0]SR1,SR2,SR2_OUT,ALU_OUT;
    //wire [15:0] SEXT4,SEXT8;//符号扩展，功能之一：把五位的立即数变为十六位
    wire [15:0] SEXT4;//符号扩展，功能之一：把五位的立即数变为十六位
    //DFF IR(.CLK(CLK),.D(BUS),.Q(IR_OUT),.LD(LD_IR));
    register_16#(16) IR(.DATA_IN(BUS),.DATA_OUT(IR_OUT),.LD(LD_IR));
    assign OPcode      = IR_OUT[15:12];//与第五位数据一起送到状态机中
    assign Dst_addr    = IR_OUT[11:9];//目的寄存器地址
    assign Src1_addr   = IR_OUT[8:6];//源寄存器地址
    assign Src2_addr   = IR_OUT[2:0];
    assign SEXT4[15:5] = {11{IR_OUT[4]}};//ADD指令立即数的符号扩展
    assign SEXT4[4:0]  = IR_OUT[4:0];
    assign SEXT8[8:0]  = IR_OUT[8:0];
    assign SEXT8[15:9] = IR_OUT[8];//LD指令地址的符号扩展
    assign ALU_SEL     = IR_OUT[15:14];//控制ALU的运算模式   
    //assign OFFSET    = SR1;//JMPinstruction 寄存器的值取出后输入给 PC 计数器，以进行无条件的程序跳转
    register #(16,3) Registerfile(.SR1(Src1_addr),.SR2(Src2_addr),.DR(Dst_addr),.DR_IN(BUS),.LD(LD_Registerfile),.SR1_OUT(SR1_OUT),.SR2_OUT(SR2_OUT),.CLK(CLK));
    mux_2to1 #(16) SR2MUX(.D_IN0(SR2_OUT),.D_IN1(SEXT4),.SEL(SR2MUX_SEL),.D_OUT(SR2));
    /* NEED TO FIX!!!
       3basic to advanced ALU */
    ALU_3basic #(16) ALU(.OP_A(SR1_OUT),.OP_B(SR2),.ALUK(ALU_SEL),.Y(ALU_OUT),.CYO());//这里OP_A = 0为测试修改,OP_A = SR1_OUT

    tristate #(16) tri_ALU(.D_OUT(BUS),.D_IN(ALU_OUT),.SEL(tri_ALU_SEL));
    
    
    /**********************************/
    //              FSM	   	  //
    /**********************************/
    FSM FSM(.CLK(CLK),.Reset(RESET),.INSTR(IR_OUT),.INSTR_5(),.PCSEL(PCSEL),.LD_PC(LD_PC),.ADDR1MUX_SEL(ADDR1MUX_SEL),.ADDR2MUX_SEL(ADDR2MUX_SEL),
    .MARMUX_SEL(MARMUX_SEL),.tri_PC_SEL(tri_PC_SEL),.LD_MAR(LD_MAR),.RAM_WE(RAM_WE),.MDR_SEL(MDR_SEL),.LD_MDR(LD_MDR),.tri_RAM_SEL(tri_RAM_SEL),
    .LD_IR(LD_IR),.LD_Registerfile(LD_Registerfile),.SR2MUX_SEL(SR2MUX_SEL),.ALU_SEL(ALU_SEL),.tri_ALU_SEL(tri_ALU_SEL),.SR1(Src1_addr),.SR2(Src2_addr),.DR(Dst_addr));
    
    
    
endmodule
